import os
from abc import abstractmethod

from common.context.base_entity import BaseResult
from common.context.global_context import GlobalContext
from database.elasticsearch.es import ES
from database.mapper import boards_info, stock_day_k
from service import period_service
from utils import statisticalutil, parse_util, functions, dict_util, read_config, doc_util


class BigDataTrain(BaseResult):
    def __init__(self, code):
        super().__init__()
        self.code = code  # 编码
        self.income_ext_data = None  # 扩展传入信息,没有传空

    # 执行策略
    @abstractmethod
    def train(self):
        print('开始执行数据训练' + str(self.code))


class BigDataTrain1(BigDataTrain):
    def train(self):
        # l2k1(GlobalContext(self.code))
        j1s2_ave(GlobalContext(self.code))
        return self


# 用移动平均线求相似度
def j1s2_ave(glc: GlobalContext):
    # 计算周期
    period_service.cal_period(glc)
    np = int(glc.result['period'] * glc.result['np'])
    # 找到连2
    ks7 = glc.get_ks_size_desc_member(260 * 7 + 70)
    ks7.reverse()
    ave7 = functions.AVE(functions.parse_x(ks7, 'rq', 'sp'), 5)
    ks7 = ks7[-len(ks7) + 30:]
    # ave7_x = ave7[-len(ks7):]
    for i in range(len(ks7) - 4):
        if ks7[i].get('sp') > ks7[i + 1].get('sp') < ks7[i + 2].get('sp') < ks7[i + 3].get('sp'):
            rq = ks7[i + 1].get('rq')
            ks_period = glc.get_ks_date_size_desc_member(rq, np)  # 逆序
            ave_period = get_ave_period(ave7, rq, np)  # 正序
            glc.result_dict_list_add('l2', {'rq': rq, 'ks_period': ks_period, 'ave_period': ave_period})
    l2_list = glc.result.get('l2')
    l2_list_len = len(l2_list)
    print(l2_list_len)
    for i in range(l2_list_len):
        count = 0
        for j in range(l2_list_len):
            if i == j:
                continue
            sccc = statisticalutil.correlation(parse_util.list_dict_to_list(l2_list[i].get('ave_period'), 'value'),
                                               parse_util.list_dict_to_list(l2_list[j].get('ave_period'), 'value'))
            if sccc > 0.8:
                count += 1
        print('I==' + str(i) + "相似数:" + str(count) + ",相似度:" + str(count / l2_list_len))

    # k1 逻辑
    print('看1逻辑')

    gl_stock_list = []
    gl_bs = boards_info.select_stock_code(glc.code)
    for board in gl_bs:
        gl_ss = boards_info.select_board_detail(board.get('board_code'))
        for stock in gl_ss:
            gl_stock_list.append(stock.get('code'))
    gl_stock_list = list(set(gl_stock_list))
    result_dict = {}
    for gl_stock in gl_stock_list:
        glg = GlobalContext(gl_stock.get('code'))
        glg_ks_all = glg.get_all_k_line()
        glg_ks_all.reverse()
        glg_ks_all_dict = parse_util.list_to_linked_list_map(glg_ks_all, 'rq')
        ave_x_all = functions.AVE(functions.parse_x(glg_ks_all, 'rq', 'sp'), 5)
        for i in range(l2_list_len):
            ave_period = parse_util.list_dict_to_list(l2_list[i].get('ave_period'), 'value')
            for i in range(len(ave_x_all) - np):
                if (functions.CORRELATION(ave_period, ave_x_all[i, i + np])) > 0.8:
                    node0 = glg_ks_all_dict.get(ave_x_all[i + np - 1].get('rq'))
                    node1 = node0.next
                    if node1.data.get('sp') > node0.data.get('sp'):
                        dict_util.put_list(result_dict, ave_period.get('rq'),
                                           {'code': gl_stock.get('code'),
                                            'rq': ave_x_all[i + np - 1]})


# 正排序
def get_ave_period(ave_x, rq, np: int):
    ave_period = []
    for i in range(len(ave_x)):
        if ave_x[i].get('rq') == rq:
            for j in range(np):
                ave_period.append(ave_x[max(i - np + j, 0)])
    ave_period.reverse()
    return ave_period


def j2s3(glc: GlobalContext):
    # 计算周期
    period_service.cal_period(glc)
    # 找到连2
    ks360 = glc.get_ks_size_desc_member(360)
    for i in range(len(ks360) - 5):
        if ks360[i].get('sp') > ks360[i + 1].get('sp') > ks360[i + 2].get('sp') > ks360[i + 3].get('sp') \
                < ks360[i + 4].get('sp') < ks360[i + 5].get('sp'):
            # print('出现连续两次增长')
            rq = ks360[i + 2].get('rq')
            ks_period = glc.get_ks_date_size_desc_member(rq, int(glc.result['period'] * glc.result['np']))
            # io_period = glc.get_io_all()
            glc.result_dict_list_add('l2', {'rq': rq, 'ks_period': ks_period})
    l2_list = glc.result.get('l2')
    l2_list_len = len(l2_list)
    print(l2_list_len)
    for i in range(l2_list_len):
        count = 0
        for j in range(l2_list_len):
            if i == j:
                continue
            sccc = statisticalutil.correlation(parse_util.list_dict_to_list(l2_list[i].get('ks_period'), 'sp'),
                                               parse_util.list_dict_to_list(l2_list[j].get('ks_period'), 'sp'))
            if sccc > 0.8:
                count += 1
        print('I==' + str(i) + "相似数:" + str(count) + ",相似度:" + str(count / l2_list_len))
    # print(glc.result)


def l2k1(glc: GlobalContext):
    # 计算周期
    period_service.cal_period(glc)
    # 找到连2
    ks360 = glc.get_ks_size_desc_member(360)
    for i in range(len(ks360) - 3):
        if ks360[i].get('sp') > ks360[i + 1].get('sp') > ks360[i + 2].get('sp') < ks360[i + 3].get('sp'):
            # print('出现连续两次增长')
            rq = ks360[i + 2].get('rq')
            ks_period = glc.get_ks_date_size_desc_member(rq, int(glc.result['period'] * glc.result['np']))
            # io_period = glc.get_io_all()
            glc.result_dict_list_add('l2', {'rq': rq, 'ks_period': ks_period})
    l2_list = glc.result.get('l2')
    l2_list_len = len(l2_list)
    print(l2_list_len)
    for i in range(l2_list_len):
        count = 0
        for j in range(l2_list_len):
            if i == j:
                continue
            sccc = statisticalutil.correlation(parse_util.list_dict_to_list(l2_list[i].get('ks_period'), 'sp'),
                                               parse_util.list_dict_to_list(l2_list[j].get('ks_period'), 'sp'))
            if sccc > 0.8:
                count += 1
        print('I==' + str(i) + "相似数:" + str(count) + ",相似度:" + str(count / l2_list_len))
    # print(glc.result)


# 用移动平均线求相似度
# 结果差强人意 区分不明显 不足60% 成功率
def j1s2_ave(glc: GlobalContext):
    # 计算周期
    period_service.cal_period(glc)
    np = int(glc.result['np'])
    # 找到连2
    ks7 = glc.get_ks_size_desc_member(260 * 7 + 70)
    ks7.reverse()
    ave7 = functions.AVE(functions.parse_x(ks7, 'rq', 'sp'), 5)
    ks7 = ks7[-len(ks7) + 30:]
    # ave7_x = ave7[-len(ks7):]
    for i in range(len(ks7) - 4):
        if ks7[i].get('sp') > ks7[i + 1].get('sp') < ks7[i + 2].get('sp') < ks7[i + 3].get('sp'):
            rq = ks7[i + 1].get('rq')
            # ks_period = glc.get_ks_date_size_desc_member(rq, np)  # 逆序
            ave_period = get_ave_period(ave7, rq, np)  # 正序
            glc.result_dict_list_add('l2', {'rq': rq, 'ave_period': ave_period})
    l2_list = glc.result.get('l2')
    l2_list_len = len(l2_list)

    # k1 逻辑
    print('看1逻辑')
    gl_stock_list = []
    gl_bs = boards_info.select_stock_code(glc.code)
    for board in gl_bs:
        gl_ss = boards_info.select_board_detail(board.get('board_code'))
        for stock in gl_ss:
            gl_stock_list.append(stock.get('code'))
    gl_stock_list = list(set(gl_stock_list))
    result_dict = {}
    for gl_code in gl_stock_list:
        glg_ks_all = stock_day_k.select_all_asc(gl_code)
        ave_x_all = functions.AVE(functions.parse_x(glg_ks_all, 'rq', 'sp'), 5)
        glg_ks_all = glg_ks_all[max(-260 * 8, -len(glg_ks_all)):]
        ave_x_all = ave_x_all[-len(glg_ks_all):]
        glg_ks_all_dict = parse_util.list_to_linked_list_map(glg_ks_all, 'rq')
        for ii in range(l2_list_len):
            ave_period = l2_list[ii].get('ave_period')
            for j in range(len(ave_x_all) - np - 1):
                if (functions.CORRELATION(ave_period, ave_x_all[j: j + np])) > 0.8:
                    node0 = glg_ks_all_dict.get(ave_x_all[j + np - 1].get('key'))
                    if node0 is None or not node0.has_next():
                        continue
                    node1 = node0.next
                    dict_util.put_list(result_dict, l2_list[ii].get('rq') + 'trigger', '1')
                    if node1.data.get('sp') > node0.data.get('sp'):
                        dict_util.put_list(result_dict, l2_list[ii].get('rq'),
                                           {'code': gl_code, 'ave_x': ave_x_all[j + np - 1]})

    es = ES()
    es.module = '601600aglydsjfx'
    for key in result_dict.keys():
        if key[-7:] == 'trigger':
            count = result_dict.get(key)
            count = len(count)
            result_dict[key] = count
            value = result_dict.get(key[0:-7])
            s_len = len(value)
            if s_len / count < 0.6:
                result_dict[key[0:-7]] = "未达到要求"
                continue
            es.index({'key': value, 'count': count, 'trigger': s_len, 'rate': round(s_len / count * 100, 2)})
    doc_util.gen_new_doc(os.path.join(read_config.data_path, 'result'), glc.get_name() + '大数据分析', [str(result_dict)])
    return result_dict


def j1s3_ave(glc: GlobalContext):
    # 计算周期
    period_service.cal_period(glc)
    np = int(glc.result['np'])
    ks7 = glc.get_ks_size_desc_member(260 * 7 + 70)
    ks7.reverse()  # 正序
    ave7 = functions.AVE(functions.parse_x(ks7, 'rq', 'sp'), 5)  # 正序
    ks7 = ks7[-len(ks7) + 30:]
    ave7_new = ave7[-len(ks7):]
    for i in range(len(ave7_new) - 5):
        if ave7[i].get('value') > ave7[i + 1].get('value') \
                < ave7[i + 2].get('value') < ave7[i + 3].get('value') < ave7[i + 4].get('value'):
            rq = ave7[i + 3].get('key')
            ave_period = get_ave_period(ave7, rq, np)  # 正序
            glc.result_dict_list_add('ln', {'rq': rq, 'ave_period': ave_period})
    l2_list = glc.result.get('ln')
    l2_list_len = len(l2_list)

    # k1 逻辑
    print(date_util.get_date_time_str() + '看1逻辑')
    gl_stock_list = []
    gl_bs = boards_info.select_stock_code(glc.code)
    for board in gl_bs:
        gl_ss = boards_info.select_board_detail(board.get('board_code'))
        for stock in gl_ss:
            gl_stock_list.append(stock.get('code'))
    gl_stock_list = list(set(gl_stock_list))
    result_dict = {}
    for gl_code in gl_stock_list:
        glg_ks_all = stock_day_k.select_all_asc(gl_code)
        ave_x_all = functions.AVE(functions.parse_x(glg_ks_all, 'rq', 'sp'), 5)
        glg_ks_all = glg_ks_all[max(-260 * 8, -len(glg_ks_all)):]
        ave_x_all = ave_x_all[-len(glg_ks_all):]
        glg_ks_all_dict = parse_util.list_to_linked_list_map(glg_ks_all, 'rq')
        continue_num = 0
        for ii in range(l2_list_len):
            if continue_num > 0:
                continue_num -= 1
                continue
            ave_period = l2_list[ii].get('ave_period')
            for j in range(len(ave_x_all) - np - 1):
                c_score = functions.CORRELATION(ave_period, ave_x_all[j: j + np])
                if c_score > 0.8:
                    node0 = glg_ks_all_dict.get(ave_x_all[j + np - 1].get('key'))
                    if node0 is None or not node0.has_next():
                        continue
                    node1 = node0.next
                    dict_util.put_int_add(result_dict, l2_list[ii].get('rq') + 'trigger', 1)
                    if node1.data.get('sp') > node0.data.get('sp'):
                        dict_util.put_list(result_dict, l2_list[ii].get('rq'),
                                           {'code': gl_code, 'ave_x': ave_x_all[j + np - 1]})
                elif c_score < 0:
                    continue_num = int(np / 2)

    es = ES()
    es.module = '601600dsjfx'
    for key in result_dict.keys():
        if key[-7:] != 'trigger':
            info = result_dict.get(key)
            s_len = len(info)
            count = int(result_dict.get(key + 'trigger'))
            if s_len / count < 0.6:
                result_dict[key] = "未达到要求删除"
                continue
            es.index({'key': key, 'count': count, 'trigger': s_len, 'rate': round(s_len / count * 100, 2)})
    doc_util.gen_new_doc(os.path.join(read_config.data_path, 'result'), glc.get_name() + '大数据分析', [str(result_dict)])
    print(date_util.get_date_time_str())
    return result_dict


# 正排序
def get_ave_period(ave_x, rq, np: int):
    ave_period = []
    for i in range(len(ave_x)):
        if ave_x[i].get('key') == rq:
            for j in range(np):
                ave_period.append(ave_x[max(i - np + j, 0)])
            return ave_period
    return None

if __name__ == '__main__':
    print('test')
    # period_list = cal_period(GlobalContext('601600'))
    BigDataTrain1('601600').train()
    print('end')
